<template>
  <div id="root">
    <!-- 搜索框 -->
    <Search
      :roleQuery="roleQuery"
      @searchRole="searchRole"
    />
    <!-- 按钮序列 -->
    <ButtonVue
      @addRoleVisible="addRoleVisible"
      @assignUser="assignUser"
      @assignResourceTree="assignResourceTree"
      @refresh="refresh"
      @removeRole="removeRole"
    />
    <!-- 表格 -->
    <MainTable
      ref="tableData"
      :tableData="tableData"
      :listLoading="listLoading"
      @copyTable="copyTable"
      @updateTable="updateTable"
      @removeTable="removeTable"
      @checkPermission="checkPermission"
    />
    <!-- 角色主页分页条 -->
    <el-pagination
      :v-model="rolePage"
      :current-page.sync="rolePage.pageNum"
      :page-size="rolePage.pageSize"
      :page-sizes="[10, 15, 20, 50, 100, 200]"
      layout="total,sizes,prev, pager, next, jumper"
      :total="rolePage.total"
      @size-change="roleSizeChange"
      @current-change="roleCurrentChange"
    />
    <!-- 添加功能弹窗 -->
    <AddDialog
      ref="roleDTO"
      :adddialogVisible="adddialogVisible"
      :roleDTO="roleDTO"
      :formLabelWidth="formLabelWidth"
      :rules="rules"
      @closeDialog="closeDialog"
      @addRole="addRole"
    />
    <!--    更新的弹框-->
    <el-dialog
      title="修改角色"
      :visible.sync="updatedialogVisible"
      width="60%"
    >
      <el-form ref="roleDTO" :model="roleDTO" :rules="rules">
        <el-form-item label="角色名称" prop="name" :label-width="formLabelWidth">
          <el-input id="txtRoleName" v-model="roleDTO.name" autocomplete="off" />
        </el-form-item>
        <el-form-item label="角色编号" prop="code" :label-width="formLabelWidth">
          <el-input id="txtRoleCode" v-model="roleDTO.code" autocomplete="off" />
        </el-form-item>
        <el-form-item label="角色备注" prop="remark" :label-width="formLabelWidth">
          <el-input id="txtRemark" v-model="roleDTO.remark" autocomplete="off" />
        </el-form-item>
        <el-form-item label="是否启用">
          <template>
            <el-radio v-model="roleDTO.status" :label="1">是</el-radio>
            <el-radio v-model="roleDTO.status" :label="0">否</el-radio>
          </template>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="updatedialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="modifyRole">确 定</el-button>
      </div>
    </el-dialog>
    <!-- 分配资源功能弹窗 -->
    <el-dialog title="分配资源" :visible.sync="assigndialogVisble">
      <BossSoftTree id="TreeStyle" ref="bosssoft" :data="treeData" :showcheckbox="true" />
      <div slot="footer" class="dialog-footer">
        <el-button @click="assigndialogVisble = false">取 消</el-button>
        <el-button v-if="isPermission" type="primary" @click="assignResourceOK">确 定</el-button>
      </div>
    </el-dialog>
    <!-- 用户分配弹窗 -->
    <el-dialog
      title="用户分配"
      :visible.sync="getUserVisible"
      width="1000px"
    >
      <el-form :inline="true">
        <el-form-item label="用户名称：">
          <el-input v-model="userQuery.name" placeholder="请输入用户名称" />
        </el-form-item>
        <el-button
          style="margin-left: 5px"
          type="primary"
          @click="searchUser"
        >查询</el-button>
      </el-form>
      <el-table
        ref="userTable"
        v-loading="listLoading"
        :data="userData"
        selectable
        highlight-current-row
        height="350"
        style="width: 100%"
      >
        <el-table-column type="selection" />
        <el-table-column label="用户工号" align="center">
          <template slot-scope="scope">
            {{ scope.row.code }}
          </template>
        </el-table-column>
        <el-table-column label="用户名" align="center">
          <template slot-scope="scope">
            {{ scope.row.name }}
          </template>
        </el-table-column>
        <el-table-column label="公司" align="center" prop="company.name" />
        <el-table-column label="部门" align="center" prop="departmentVO.name" />
      </el-table>
      <!-- 用户主页分页条 -->
      <el-pagination
        :v-model="userPage"
        :current-page.sync="userPage.pageNum"
        :page-size="userPage.pageSize"
        :page-sizes="[15]"
        layout="total,sizes,prev, pager, next, jumper"
        :total="userPage.total"
        @size-change="userSizeChange"
        @current-change="userCurrentChange"
      />
      <span slot="footer" class="dialog-footer">
        <el-button @click="getUserVisible = false">取 消</el-button>
        <el-button type="primary" @click="assginRoleToUser">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
/*
 * 解构引入请求方法、$message、BossSoftTree组件
 */
import { getResource, add, remove, batchRemove, queryRoleById, modify, assignResource, commonQueryUser, assignUser } from '@/api/right/role'
import { treeQuery } from '@/api/right/resource'
import { Message } from 'element-ui'
import BossSoftTree from '@/components/Common/BossSoftTree.vue'
import ButtonVue from './Button.vue'
import MainTable from './MainTable.vue'
import AddDialog from './AddDialog.vue'
import Search from './Search.vue'

export default {
  name: 'Role',
  // 数据

  components: { BossSoftTree, ButtonVue, MainTable, AddDialog, Search },
  data() {
    return {
      // 表单规则校验
      rules: {
        name: [
          { required: true, message: '请输入角色名称', trigger: 'blur' }
        ],
        code: [
          { required: true, message: '请输入角色编号', trigger: 'blur' }
        ]
      },
      roleQuery: {
        name: ''
      },
      listLoading: false,
      // 表单数据
      tableData: [],
      userData: [],
      roleDTO: {
        name: '',
        code: '',
        remark: '',
        id: '',
        status: '',
        version: '',
        created_by: '',
        companyId: '',
        tenantId: '',
        orgId: ''
      },
      // 展示用户分配时候需要传递的参数对象
      userQuery: {},
      getUserVisible: false,
      // 资源数上传
      roleResourceDTO: {},
      resourceIdList: [],
      roleIdList: [],
      userIdList: [],
      // 分配资源数组
      assignData: [],
      // 弹窗显示部分
      isPermission: true,
      adddialogVisible: false,
      updatedialogVisible: false,
      assigndialogVisble: false,
      // 弹窗内部属性
      // 输入框宽度
      formLabelWidth: '120px',
      // 分页
      rolePage: {
        total: null,
        // 页号
        pageNum: 1,
        // 页大小
        pageSize: 10,
        pages: null
      },
      userPage: {
        total: null,
        // 页号
        pageNum: 1,
        // 页大小
        pageSize: 15,
        pages: null
      },
      // 树状结构
      treeData: []
    }
  },
  // create创建前赋值
  created() {
    this.loadResource(this.rolePage.pageNum)
  },
  // 方法开始
  methods: {
    /*
    * transform方法
    * 目的:将后端返回的数据转化成树状图
    * 方法思路:后端数据中有parentId 和 sourceType来识别树状图的数据
    * 利用forEach方法遍历数组，通过parentId判断有无父节点，将父节点push进空数组tree[]中
    * 利用多重forEach循环，判断item.parentId === parentItem.id，为父节点push子节点
    * 第二层利用了一个filter方法，感觉和forEach没有太多差别，并没有达到简化的目的。
    * filter过滤得到了有子节点数组
    */
    transform(responseData) {
      let tree = []
      responseData.forEach(parentItem => {
        if (parseInt(parentItem.parentId) === -1 && parentItem.resourceType === 2) {
          tree.push({ label: parentItem.name, id: parentItem.id, children: [] })
        }
      })
      tree.forEach(parentItem => {
        var result = responseData.filter(item => item.parentId === parentItem.id)
        result.forEach(value => {
          parentItem.children.push({
            label: value.name,
            id: value.id,
            children: []
          })
        })
      })
      tree.forEach(parentItem => {
        parentItem.children.forEach(secondParentItem => {
          responseData.forEach(item => {
            if (item.parentId === secondParentItem.id) {
              secondParentItem.children.push({
                label: item.name,
                id: item.id,
                children: []
              })
            }
          })
        })
      })
      tree.forEach(parentItem => {
        parentItem.children.forEach(secondParentItem => {
          secondParentItem.children.forEach(thirdParentItem => {
            responseData.forEach(item => {
              if (item.parentId === thirdParentItem.id) {
                thirdParentItem.children.push({
                  label: item.name,
                  id: item.id
                })
              }
            })
          })
        })
      })
      return tree
    },
    // 获取页面资源
    loadResource(pageNum) {
      this.listLoading = true
      this.roleQuery.total = this.rolePage.total
      this.roleQuery.pageNum = pageNum
      this.roleQuery.pageSize = this.rolePage.pageSize
      getResource(this.roleQuery)
        .then(response => {
          const { total, pages, data } = response
          this.rolePage.total = parseInt(total)
          this.rolePage.pages = parseInt(pages)
          this.tableData = data
          // 声明输入框字符name，判断name是否为空，若为空则全部展示，若不为空则寻找item.name等于的项
          const name = this.roleQuery.name
          if (name !== '') {
            this.tableData.find(item => {
              return item.name === this.roleQuery.name
            })
          }
          setTimeout(() => {
            this.listLoading = false
          }, 3000)
        })
        .catch(() => {
          Message({
            message: '加载资源失败',
            type: 'error'
          })
        })
    },
    /*
    *  分页功能处理
    *  主页面角色列表分页方法
    *  roleCurrentChange(当前页面页数) ->调用loadResource方法，传入当前页数
    *  roleSizeChange(当前页面条数) ->将rolePage的pageSize改成当前页面条数，并调用loadResource方法，传入页面1
    *  用户列表分页方法
    *  userCurrentChange 和 userSizeChange 方法同理
    */
    roleCurrentChange(val) {
      this.rolePage.pageNum = val
      this.loadResource(this.rolePage.pageNum)
    },
    roleSizeChange(val) {
      this.rolePage.pageSize = val
      this.loadResource(1)
    },
    userCurrentChange(val) {
      this.userPage.pageNum = val
      this.getUserResource(this.userPage.pageNum)
    },
    userSizeChange(val) {
      this.userPage.pageSize = val
      this.getUserResource(1)
    },
    addRoleVisible() {
      this.adddialogVisible = true
      this.roleDTO.status = 1
    },
    // 刷新
    refresh() {
      this.loadResource(this.rolePage.pageNum)
    },
    // 查角色
    searchRole() {
      this.loadResource(1)
    },
    // 查用户
    searchUser() {
      this.getUserResource(1)
    },
    /*
    * 添加角色
    * 通过表单数据循环判断，是否有与正在添加的编号相同的编号，有则coderepeat返回true
    * 第一步if判断表单是否填写，第二步if判断编号是否重复，有则返回提交重复编号
    * 全部通过校验，则发起请求添加数据。
    */
    closeDialog() {
      this.adddialogVisible = false
      this.$refs.roleDTO.$refs.roleDTO.resetFields()
    },
    validateRepeat(info, database) {
      let flag = false
      database.forEach(item => {
        if (info.code === item.code) {
          flag = true
        }
      })
      return flag
    },
    addRole() {
      const flag = this.validateRepeat(this.roleDTO, this.tableData)
      this.$refs.roleDTO.$refs.roleDTO.validate((valid) => {
        if (!valid) {
          Message({
            type: 'error',
            message: '提交表单内容不全'
          })
        } else if (flag) {
          Message({
            type: 'error',
            message: '编号不能重复'
          })
        } else {
          this.adddialogVisible = false
          add(this.roleDTO)
            .then(() => {
              this.loadResource(this.rolePage.pageNum)
              Message({
                message: '添加成功',
                type: 'success',
                duration: 3 * 1000
              })
            })
            .catch(() => {
              Message({
                message: '添加失败',
                type: 'error'
              })
            })
        }
      })
    },
    // 批量删除角色
    removeRole() {
      // 获取选择框数组
      const selectRole = this.$refs.tableData.$refs.tableData.selection
      // 判断是否选择1个及以上选择框
      if (selectRole.length === 0) {
        this.$message.error('请选择至少一个进行删除！')
      }
      // 设置一个数组来接收容器
      let roleInfos = new Array(selectRole.length)
      selectRole.forEach((item, index) => {
        roleInfos[index] = {
          id: item.id,
          version: item.version
        }
      })
      // 如果选择的数据不是0，则给出删除提示
      if (roleInfos.length !== 0) {
        this.$confirm('确定删除记录吗', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
        // 确定后进行.then进行批量删除
          .then(() => {
            batchRemove(roleInfos)
              .then(() => {
                Message({
                  message: '删除成功',
                  type: 'success'
                })
                this.listLoading = true
                this.loadResource(this.rolePage.pageNum)
                setTimeout(() => {
                  this.listLoading = false
                }, 3000)
              })
              .catch(() => {
                Message({
                  message: '已取消删除',
                  type: 'info'
                })
              })
          })
      } else {
        this.$message({
          message: '请选择需要删除的数据',
          type: 'warning'
        })
      }
    },
    // 删除角色
    removeTable(row) {
      this.$confirm('确定删除记录吗', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(() => {
          remove(row.id, row.version)
            .then(() => {
              this.loadResource(1)
              Message({
                type: 'success',
                message: '删除成功！',
                duration: 3 * 1000
              })
            })
            .catch(() => {
              Message({
                type: 'error',
                message: '删除失败！',
                duration: 3 * 1000
              })
            })
        })
    },
    // 更新角色-1.打开更新框-通过id查询角色信息
    updateTable(row) {
      this.updatedialogVisible = true
      queryRoleById(row.id)
        .then(res => {
          this.roleDTO = res
        })
        .catch(err => {
          Message({
            message: err,
            type: 'error'
          })
        })
    },
    // 更新修改角色-2.提交修改表单
    modifyRole() {
      const roleVo = this.roleDTO
      this.$refs.roleDTO.$refs.roleDTO.validate(valid => {
        if (!valid) {
          Message({
            type: 'error',
            message: '提交信息无效'
          })
        } else {
          this.updatedialogVisible = false
          modify(roleVo)
            .then(() => {
              Message({
                type: 'success',
                message: '修改成功!'
              })
              this.loadResource(1)
            })
            .catch(() => {
              Message({
                type: 'error',
                message: '修改失败'
              })
            })
        }
      })
    },
    // 复制角色
    copyTable(row) {
      this.adddialogVisible = true
      queryRoleById(row.id)
        .then((res) => {
          this.roleDTO = res
          // console.log(this.roleDTO)
        })
        .catch(() => {
          Message({
            message: '网络错误',
            type: 'error'
          })
        })
    },
    // 资源分配
    assignResourceTree() {
      const selectRole = this.$refs.tableData.$refs.tableData.selection
      if (selectRole.length === 0) {
        Message({
          type: 'error',
          message: '请选择至少一个用户'
        })
      } else {
        this.isPermission = true
        this.assigndialogVisble = true
        const resourceQuery = {}
        resourceQuery.pageSize = 1000
        treeQuery(resourceQuery)
          .then((res) => {
            this.treeData = this.transform(res.data)
            selectRole.forEach(item => {
              this.roleIdList.push(item.id)
            })
            if (selectRole.length === 1) {
              this.setChecked(selectRole[0].id)
            }
          })
          .catch(() => {
            Message({
              type: 'error',
              message: 'Net Error!'
            })
          })
      }
    },
    /*
     * 确认分配资源
     * this.$refs.bosssoft 获取bosssoft组件，再通过.refs.tree获取组件中的el-tree
     * getCheckedNodes()获取所有被选中的结点，返回数组
     *  通过遍历数组，将node-key="id"的id赋值给resourceIdList
     * getHalfCheckedKeys()返回目前半选中的节点的 key 所组成的数组
     * 通过遍历将key赋值给resourceIdList
     * 声明roleResourceDTO对象，传入roleIds（选中角色id）和resourceIds（check中的id）
     * 分配完了之后需要重置这两个属性
     */
    assignResourceOK() {
      const list = this.$refs.bosssoft.$refs.tree.getCheckedNodes()
      const listParent = this.$refs.bosssoft.$refs.tree.getHalfCheckedKeys()
      listParent.forEach(item => {
        this.resourceIdList.push(item)
      })
      list.forEach(item => {
        this.resourceIdList.push(item.id)
      })
      // console.log('数组为' + this.resourceIdList)
      const roleResourceDTO = {
        roleIds: this.roleIdList,
        resourceIds: this.resourceIdList
      }
      assignResource(roleResourceDTO)
        .then(() => {
          Message({
            message: '分配成功',
            type: 'success'
          })
          // 重置
          this.assigndialogVisble = false
          this.resourceIdList = []
          this.roleIdList = []
          // 进行重新加载
          this.loadResource(1)
        })
        .catch(() => {
          Message({
            message: '分配失败',
            type: 'error'
          })
        })
        .finally(() => {
          this.selectionData = []
        })
    },
    // 设置check属性
    setChecked(roldId) {
      const resourceQuery = {}
      resourceQuery.roleId = roldId
      resourceQuery.pageSize = 1000
      // console.log(resourceQuery)
      treeQuery(resourceQuery)
        .then((res) => {
          const { data } = res
          data.forEach((item) => {
            this.$refs.bosssoft.$refs.tree.setChecked(item.id, true, false)
          })
        }).catch(() => {
          Message({
            message: 'Net Error',
            type: 'error'
          })
        })
    },
    // 禁用所有树节点
    disableTreeNode(treedata) {
      treedata.forEach((item) => {
        this.$set(item, 'disabled', true)
        if (item.children && item.children.length > 0) {
          item.children = this.disableTreeNode(item.children)
        }
      })
      return treedata
    },
    // 查看权限
    checkPermission(row) {
      // console.log('查看权限' + row.id)
      this.assigndialogVisble = true
      this.isPermission = false
      const resourceQuery = {}
      resourceQuery.pageSize = 1000
      treeQuery(resourceQuery)
        .then((res) => {
          this.treeData = this.transform(res.data)
          this.treeData = this.disableTreeNode(this.treeData)
          this.setChecked(row.id)
        })
        .catch(() => {
          Message({
            message: 'Error',
            type: 'error'
          })
        })
    },
    // 分配用户
    assignUser() {
      const selectRole = this.$refs.tableData.$refs.tableData.selection
      if (selectRole.length === 0) {
        Message({
          type: 'error',
          message: '请选择至少一个用户'
        })
      } else {
        selectRole.forEach(item => {
          this.roleIdList.push(item.id)
        })
        console.log('roleIdList', this.roleIdList)
        this.getUserVisible = true
        this.getUserResource(1)
      }
    },
    // 获取用户资源
    getUserResource(pageNum) {
      this.userQuery.pageSize = this.userPage.PageSize
      this.userQuery.total = this.userPage.total
      this.userQuery.pageNum = pageNum
      commonQueryUser(this.userQuery)
        .then(res => {
          console.log(res)
          const { total, pages, data } = res
          this.userData = data
          this.userPage.total = parseInt(total)
          this.userPage.pages = parseInt(pages)
        })
        .catch(() => {
          Message({
            message: 'Error',
            type: 'error'
          })
        })
    },
    // 分配用户
    assginRoleToUser() {
      const selectUser = this.$refs.userTable.selection
      if (selectUser.length === 0) {
        Message({
          message: '请至少选择一个用户',
          type: 'info'
        })
      } else {
        selectUser.forEach(item => {
          this.userIdList.push(item.id)
        })
        const userRoleDTO = {
          roleIds: this.roleIdList,
          userIds: this.userIdList
        }
        this.getUserVisible = false
        // console.log(userRoleDTO)
        assignUser(userRoleDTO)
          .then((res) => {
            Message({
              message: '分配成功',
              type: 'success'
            })
            this.userIdList = []
            this.roleIdList = []
            this.loadResource(1)
          })
          .catch(() => {
            Message({
              message: '分配失败',
              type: 'error'
            })
          })
      }
    }
  }
}
</script>
<style scoped>
  #root{
    margin-left:20px;
  }
  #TreeStyle{
    border: 1px solid black;
    overflow-y: scroll;
    height: 400px;
  }
</style>
